package com.chukun.netty.nio;

import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.Random;

/**
 * nio的基本操作
 */
public class NIOOperator {


   @Test
   public void test01(){
        IntBuffer buffer = IntBuffer.allocate(10);
        Random random = new Random();
        for(int i=0;i<10;i++){
            buffer.put(random.nextInt());
        }
        //翻转操作
        buffer.flip();
        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }
    }

    /**
     * slice方法会截取一段buffer的数据，与原来的buffer共享数据
     */
    @Test
    public void test02(){
        ByteBuffer buffer = ByteBuffer.allocate(10);
        for(int i=0;i<10;i++){
            buffer.put((byte)i);
        }

        buffer.position(2);
        buffer.limit(6);
        ByteBuffer slice = buffer.slice();
        for(int i=0;i<slice.capacity();i++){
            byte b = slice.get(i);
            slice.put(i,(byte)((int)(b)*2));
        }

        buffer.position(0);
        buffer.limit(buffer.capacity());
        for(int i=0;i<buffer.capacity();i++){
            System.out.print(buffer.get(i)+" ");
        }
    }

    /**
     * 只读的buffer put操作会抛异常
     */
    @Test
    public void test03(){
        ByteBuffer buffer = ByteBuffer.allocate(10);
        for(int i=0;i<10;i++){
            buffer.put((byte)i);
        }
        ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
        readOnlyBuffer.put(1,(byte)2);
    }

    /**
     * Scattering 与 Gathering的基本操作
     */
    @Test
    public void test04() throws IOException {
        ServerSocketChannel socketChannel = ServerSocketChannel.open();
        InetSocketAddress address = new InetSocketAddress(8899);
        socketChannel.socket().bind(address);

        //定义ByteBuffer的数据
        ByteBuffer headBuf = ByteBuffer.allocate(2);
        ByteBuffer bodyBuf = ByteBuffer.allocate(3);
        ByteBuffer footBuf = ByteBuffer.allocate(4);
        ByteBuffer [] buffers = new ByteBuffer[]{headBuf,bodyBuf,footBuf};

        int maxLength = headBuf.capacity()+bodyBuf.capacity()+footBuf.capacity();
        SocketChannel accept = socketChannel.accept();
        while(true) {
            int readLength = 0;
            while (readLength < maxLength) {
                long r = accept.read(buffers);
                readLength += r;
                System.out.println("bytereaded: " + readLength);
                Arrays.stream(buffers).map(buf -> "position: " + buf.position() + " limit: " + buf.limit())
                        .forEach(System.out::println);
            }
            //写回channel,翻转操作
            Arrays.stream(buffers).forEach(buf->{
                buf.flip();
            });
            int byteWritted = 0;
            while (byteWritted < maxLength) {
                long w = accept.write(buffers);
                byteWritted += w;
                Arrays.asList(buffers).stream().map(buf -> "position: " + buf.position() + " limit: " + buf.limit())
                        .forEach(System.out::println);
            }

            Arrays.stream(buffers).forEach(buf -> {
                buf.clear();
            });
        }
    }
}
